/**
 * @author Jason Pratt, Dennis Cosgrove
 */

package edu.cmu.cs.stage3.alice.authoringtool.dialog;

import edu.cmu.cs.stage3.resourceBundle.I18n;

import java.awt.GridBagConstraints;
import java.awt.Insets;

import edu.cmu.cs.stage3.alice.authoringtool.AuthoringTool;
import edu.cmu.cs.stage3.alice.authoringtool.AuthoringToolResources;
import edu.cmu.cs.stage3.alice.core.Property;
import edu.cmu.cs.stage3.alice.core.event.ChildrenListener;
import edu.cmu.cs.stage3.alice.core.event.PropertyListener;
import edu.cmu.cs.stage3.alice.core.reference.ObjectArrayPropertyReference;
import edu.cmu.cs.stage3.alice.core.reference.PropertyReference;
import edu.cmu.cs.stage3.swing.ContentPane;
import edu.cmu.cs.stage3.swing.DialogManager;
import edu.cmu.cs.stage3.util.HowMuch;

public class DeleteContentPane extends ContentPane implements edu.cmu.cs.stage3.alice.core.event.PropertyListener, edu.cmu.cs.stage3.alice.core.event.ChildrenListener{

 public final static int LESS_DETAIL_MODE = 0;
 public final static int MORE_DETAIL_MODE = 1;

 protected int mode = -1;
 protected static AuthoringTool authoringTool;
 protected edu.cmu.cs.stage3.alice.authoringtool.util.ImagePanel errorIconPanel = new edu.cmu.cs.stage3.alice.authoringtool.util.ImagePanel();
 protected edu.cmu.cs.stage3.alice.authoringtool.util.ElementPopupUtilities.DeleteRunnable deleteRunnable;
 protected edu.cmu.cs.stage3.alice.core.Element danglingElementToClear;

 // From 'src/edu/cmu/cs/stage3/alice/authoringtool/util/ElementPopupUtilities.java'
 public static void showDeleteDialog (edu.cmu.cs.stage3.alice.authoringtool.util.ElementPopupUtilities.DeleteRunnable deleteRunnable, AuthoringTool authoringTool) {
  DeleteContentPane dcp = new DeleteContentPane( authoringTool );
  dcp.setDeleteRunnable( deleteRunnable );
  dcp.refresh();
  if (DialogManager.showDialog(deleteRunnable, dcp) == ContentPane.OK_OPTION) { //L
   deleteRunnable.run();  
   }
  }

 public DeleteContentPane (AuthoringTool authoringTool) {
  DeleteContentPane.authoringTool = authoringTool;
  jbInit();
  java.net.URL errorImageResources = edu.cmu.cs.stage3.alice.authoringtool.JAlice.class.getResource( "images/error.gif" );
  errorIconPanel.setImage( java.awt.Toolkit.getDefaultToolkit().createImage( errorImageResources ) );
  iconPanel.add( errorIconPanel, java.awt.BorderLayout.CENTER );

  messageArea.setLineWrap( true );
  messageArea.setWrapStyleWord( true );
  messageArea.setOpaque( false );

  referencesList.setCellRenderer( new edu.cmu.cs.stage3.alice.authoringtool.util.PropertyReferenceListCellRenderer() );
  referencesList.addListSelectionListener( new ReferencesSelectionListener() );

  setPreferredSize( new java.awt.Dimension( 600, 300 ) );
  }

 //Rem @Override
 public String getTitle () {
  return "iVProg - Can't Delete";
  }
 //Rem @Override
 public void addOKActionListener (java.awt.event.ActionListener l) {
  okayButton.addActionListener( l );
  }
 //Rem @Override
 public void removeOKActionListener (java.awt.event.ActionListener l) {
  okayButton.removeActionListener( l );
  }
 //Rem @Override
 public void addCancelActionListener (java.awt.event.ActionListener l) {
  cancelButton.addActionListener( l );
  }
 //Rem @Override
 public void removeCancelActionListener (java.awt.event.ActionListener l) {
  cancelButton.removeActionListener( l );
  }

 //Rem @Override
 public void postDialogShow (javax.swing.JDialog dialog) {
  stopListening();
  super.postDialogShow( dialog );
  }


 public void setDeleteRunnable (edu.cmu.cs.stage3.alice.authoringtool.util.ElementPopupUtilities.DeleteRunnable deleteRunnable) {
  this.deleteRunnable = deleteRunnable;
  }

 public void startListening () {
  javax.swing.ListModel list = referencesList.getModel();
  for (int i=0; i<list.getSize(); i++) {
   if (list.getElementAt(i) instanceof PropertyReference) {
    PropertyReference reference = (PropertyReference)list.getElementAt(i);
    edu.cmu.cs.stage3.alice.core.Element source = reference.getProperty().getOwner();
    listenUpToRootElement(source);
    if (source instanceof edu.cmu.cs.stage3.alice.core.question.PropertyValue) {
     edu.cmu.cs.stage3.alice.core.Property[] properties = source.getParent().getProperties();
     //LOB for (Property propertie : properties)
     int t_tam = properties!=null ? properties.length : 0;
     for (int i_i=0; i_i<t_tam; i_i++) {
      if (properties[i_i].get() == source) { //L if (propertie.get() == source)
        properties[i_i].addPropertyListener(this); //L propertie.addPropertyListener(this);
       }
      }
     }
    else if (reference instanceof ObjectArrayPropertyReference) {
     ObjectArrayPropertyReference oAPR = (ObjectArrayPropertyReference)reference;
     PropertyReference[] references = oAPR.getReference().getPropertyReferencesTo( deleteRunnable.getElement(), HowMuch.INSTANCE_AND_ALL_DESCENDANTS, true, true );
     if (references != null && references.length > 0) {
      reference.getProperty().addPropertyListener(this);
      }
     }
    else {
     reference.getProperty().addPropertyListener(this);
     }
    }
   }
  }

 public void stopListening () {
  javax.swing.ListModel list = referencesList.getModel();
  for (int i=0; i<list.getSize(); i++) {
   if (list.getElementAt(i) instanceof PropertyReference) {
    PropertyReference reference = (PropertyReference)list.getElementAt(i);
    edu.cmu.cs.stage3.alice.core.Element source = reference.getProperty().getOwner();
    stopListeningUpToRootElement(source);
    if (source instanceof edu.cmu.cs.stage3.alice.core.question.PropertyValue) {
     if (source.getParent() != null) {
      edu.cmu.cs.stage3.alice.core.Property[] properties = source.getParent().getProperties();
      //LOB for (Property propertie : properties)
      int t_tam = properties!=null ? properties.length : 0;
      for (int i_i=0; i_i<t_tam; i_i++) {
       if (properties[i_i].get() == source) { //L if (propertie.get() == source)
        properties[i_i].removePropertyListener(this); //L propertie.removePropertyListener(this);
        }
       }
      }
     }
    else if (reference instanceof ObjectArrayPropertyReference) {
     PropertyReference[] references = reference.getProperty().getOwner().getPropertyReferencesTo( deleteRunnable.getElement(), HowMuch.INSTANCE_AND_ALL_DESCENDANTS, true, true );
     if (references != null && references.length > 0) {
      reference.getProperty().removePropertyListener(this);
      }
     }
    else {
     reference.getProperty().removePropertyListener(this);
     }
    }
   }
  } // void stopListening()

 public void propertyChanging (edu.cmu.cs.stage3.alice.core.event.PropertyEvent propertyEvent) {
  }

 public void propertyChanged (edu.cmu.cs.stage3.alice.core.event.PropertyEvent propertyEvent) {
  refresh();
  }

 public void childrenChanging (edu.cmu.cs.stage3.alice.core.event.ChildrenEvent childrenEvent) {
  danglingElementToClear = childrenEvent.getParent();
  }

 public void childrenChanged (edu.cmu.cs.stage3.alice.core.event.ChildrenEvent childrenEvent) {
  stopListeningUpToRootElement(danglingElementToClear);
  refresh();
  }

 protected void listenUpToRootElement (edu.cmu.cs.stage3.alice.core.Element current) {
  if (current != null) {
   boolean alreadyChildrenListening = false;
   edu.cmu.cs.stage3.alice.core.event.ChildrenListener[] childrenListeners = current.getChildrenListeners();
   //LOB for (ChildrenListener childrenListener : childrenListeners)
   int t_tam = childrenListeners!=null ? childrenListeners.length : 0;
   for (int i_i=0; i_i<t_tam; i_i++) {
    if (childrenListeners[i_i] == this) { //L if (childrenListener == this )
     alreadyChildrenListening = true;
     }
    }
   if (! alreadyChildrenListening) {
    current.addChildrenListener( this );
    }
   edu.cmu.cs.stage3.alice.core.Property[] properties = current.getProperties();
   //LOB for (Property propertie : properties)
   t_tam = properties!=null ? properties.length : 0;
   for (int i_i=0; i_i<t_tam; i_i++) {
    edu.cmu.cs.stage3.alice.core.event.PropertyListener[] propListeners = properties[i_i].getPropertyListeners(); //L propertie.getPropertyListeners();
    boolean alreadyPropListening = false;
    //LOB for (PropertyListener propListener : propListeners)
    int tt_tam = propListeners!=null ? propListeners.length : 0;
    for (int i_j=0; i_j<tt_tam; i_j++) {
     if (propListeners[i_j] == this) { //L if (propListener == this) {
      alreadyPropListening = true;
      }
     } // for (int i_j=0; i_j<t_tam; i_j++)
    if (!alreadyPropListening) {
     properties[i_i].addPropertyListener(this); //L propertie.addPropertyListener(this);
     }
    } 
   listenUpToRootElement(current.getParent());
   }
  }

 protected void stopListeningUpToRootElement (edu.cmu.cs.stage3.alice.core.Element current) {
  if (current != null) {
   boolean alreadyChildrenListening = false;
   edu.cmu.cs.stage3.alice.core.event.ChildrenListener[] childrenListeners = current.getChildrenListeners();
   //LOB for (ChildrenListener childrenListener : childrenListeners)
   int t_tam = childrenListeners!=null ? childrenListeners.length : 0;
   for (int i_i=0; i_i<t_tam; i_i++) {
    if (childrenListeners[i_i] == this) { //L if (childrenListener == this )
     alreadyChildrenListening = true;
     }
    } // for (int i_i=0; i_i<t_tam; i_i++)
   if (alreadyChildrenListening) {
    current.removeChildrenListener( this );
    }
   edu.cmu.cs.stage3.alice.core.Property[] properties = current.getProperties();
   //LOB for (Property propertie : properties)
   t_tam = properties!=null ? properties.length : 0;
   for (int i_i=0; i_i<t_tam; i_i++) {
    edu.cmu.cs.stage3.alice.core.event.PropertyListener[] propListeners = properties[i_i].getPropertyListeners(); //L propertie.getPropertyListeners();
    boolean alreadyPropListening = false;
    //LOB for (PropertyListener propListener : propListeners)
    int tt_tam = propListeners!=null ? propListeners.length : 0;
    for (int i_j=0; i_j<tt_tam; i_j++) {
     if (propListeners[i_j] == this) { //L if (propListener == this)
      alreadyPropListening = true;
      }
     }
    if (alreadyPropListening) {
     properties[i_i].removePropertyListener(this); //L propertie.removePropertyListener(this);
     }
    } 
   stopListeningUpToRootElement(current.getParent());
   }
  }

 public void refresh () {
  if (deleteRunnable != null) {
   edu.cmu.cs.stage3.alice.core.Element element = deleteRunnable.getElement();
   String elementRepr = AuthoringToolResources.getReprForValue( element );

   PropertyReference[] references = element.getRoot().getPropertyReferencesTo( element, HowMuch.INSTANCE_AND_ALL_DESCENDANTS, true, true );

   if (references.length > 0) {
    AuthoringToolResources.garbageCollectIfPossible( references );
    references = element.getRoot().getPropertyReferencesTo( element, HowMuch.INSTANCE_AND_ALL_DESCENDANTS, true, true );
    }

   stopListening();
   referencesList.setListData( references );
   startListening();

   if (references.length > 0) {
    okayButton.setEnabled( false );
    removeReferenceButton.setEnabled( true );
    removeAllReferenceButton.setEnabled( true );
    messageArea.setText( elementRepr + " cannot be deleted because other parts of the World contain references to it. You will need to remove these references in order to delete " + elementRepr + ".\n\n" +
    "Select each reference below, and either remove the reference manually, or click the Remove Reference button to have the reference removed by the system." );
    referencesList.setSelectedIndex( 0 );
   } else {
    okayButton.setEnabled( true );
    removeReferenceButton.setEnabled( false );
    removeAllReferenceButton.setEnabled( false );
    messageArea.setText( "All references have now been deleted.  Click Okay to delete " + elementRepr + "." );
    setDialogTitle( "iVProg - Can Delete" );
    }
   }
  }


 class ReferencesSelectionListener implements javax.swing.event.ListSelectionListener {
  public void valueChanged (javax.swing.event.ListSelectionEvent ev) {
   }
  }

 void removeReferenceButton_actionPerformed (java.awt.event.ActionEvent e) {
  PropertyReference reference = (PropertyReference)referencesList.getSelectedValue();
  if (reference != null) {
   edu.cmu.cs.stage3.alice.core.Element source = reference.getProperty().getOwner();
   edu.cmu.cs.stage3.alice.core.Element sourceParent = source.getParent();
   if (source instanceof edu.cmu.cs.stage3.alice.core.response.CallToUserDefinedResponse ||
     source instanceof edu.cmu.cs.stage3.alice.core.question.userdefined.CallToUserDefinedQuestion ||
     source instanceof edu.cmu.cs.stage3.alice.core.question.PropertyValue) {
    //need to check to see if it's just a call, or it's part of a property...
    if (sourceParent instanceof edu.cmu.cs.stage3.alice.core.response.CompositeResponse) {
     source.removeFromParent();
     }
    else {
     edu.cmu.cs.stage3.alice.core.Property[] properties = sourceParent.getProperties();
     //LOB for (Property propertie : properties)
     int t_tam = properties!=null ? properties.length : 0;
     for (int i_i=0; i_i<t_tam; i_i++) {
      if (properties[i_i].get() == source) { //L if (propertie.get() == source)
       properties[i_i].removePropertyListener(this); //L propertie.removePropertyListener(this);
       properties[i_i].set(AuthoringToolResources.getDefaultValueForClass( properties[i_i].getValueClass() )); //L propertie.set(AuthoringToolResources.getDefaultValueForClass(propertie...));
       }
      }
     }
    }
   else if (reference instanceof ObjectArrayPropertyReference) {
    ObjectArrayPropertyReference oAPR = (ObjectArrayPropertyReference)reference;
    oAPR.getObjectArrayProperty().set(oAPR.getIndex(), null);
    PropertyReference[] references = oAPR.getProperty().getOwner().getPropertyReferencesTo( deleteRunnable.getElement(), HowMuch.INSTANCE_AND_ALL_DESCENDANTS, true, true );
    if (references == null || references.length < 1) {
     reference.getProperty().removePropertyListener(this);
     }
    }
   else {
    reference.getProperty().removePropertyListener(this);
    reference.getProperty().set( AuthoringToolResources.getDefaultValueForClass( reference.getProperty().getValueClass() ) );
    }
   refresh();
   }
  }

 void removeAllReferenceButton_actionPerformed(java.awt.event.ActionEvent e) {
  stopListening();
  for (int i=0; i<referencesList.getModel().getSize(); i++) {
   PropertyReference reference = (PropertyReference)referencesList.getModel().getElementAt(i);
   if (reference != null) {
    edu.cmu.cs.stage3.alice.core.Element source = reference.getProperty().getOwner();
    edu.cmu.cs.stage3.alice.core.Element sourceParent = source.getParent();
    if (source instanceof edu.cmu.cs.stage3.alice.core.response.CallToUserDefinedResponse ||
      source instanceof edu.cmu.cs.stage3.alice.core.question.userdefined.CallToUserDefinedQuestion ||
      source instanceof edu.cmu.cs.stage3.alice.core.question.PropertyValue) {
     //need to check to see if it's just a call, or it's part of a property...
     if (sourceParent instanceof edu.cmu.cs.stage3.alice.core.response.CompositeResponse) {
      source.removeFromParent();
     }
     else {
      edu.cmu.cs.stage3.alice.core.Property[] properties = sourceParent.getProperties();
      //LOB for (Property propertie : properties)
      int t_tam = properties!=null ? properties.length : 0;
      for (int i_i=0; i_i<t_tam; i_i++) {
       if (properties[i_i].get() == source) { //L if (propertie.get() == source)
        properties[i_i].removePropertyListener(this); //L propertie.removePropertyListener(this);
        properties[i_i].set(AuthoringToolResources.getDefaultValueForClass( properties[i_i].getValueClass() )); //L propertie.set(AuthoringToolResources.getDefaultValueForClass(propertie...));
       }
      }

     }
    }
    else if (reference instanceof ObjectArrayPropertyReference) {
     ObjectArrayPropertyReference oAPR = (ObjectArrayPropertyReference)reference;
     oAPR.getObjectArrayProperty().set(oAPR.getIndex(), null);
     PropertyReference[] otherReferences = oAPR.getProperty().getOwner().getPropertyReferencesTo( deleteRunnable.getElement(), HowMuch.INSTANCE_AND_ALL_DESCENDANTS, true, true );
     if (otherReferences == null || otherReferences.length < 1) {
      reference.getProperty().removePropertyListener(this);
     }
    }
    else {
     reference.getProperty().removePropertyListener(this);
     reference.getProperty().set( AuthoringToolResources.getDefaultValueForClass( reference.getProperty().getValueClass() ) );
    }
   }
  }
  refresh();
 }

 /////////////////////
 // Autogenerated
 /////////////////////

 java.awt.BorderLayout borderLayout1 = new java.awt.BorderLayout();
 javax.swing.JPanel buttonPanel = new javax.swing.JPanel();
 javax.swing.JPanel mainPanel = new javax.swing.JPanel();
 javax.swing.JButton okayButton = new javax.swing.JButton();
 javax.swing.JButton removeReferenceButton = new javax.swing.JButton();
 javax.swing.JButton removeAllReferenceButton = new javax.swing.JButton();
 javax.swing.JPanel iconPanel = new javax.swing.JPanel();
 javax.swing.JPanel messagePanel = new javax.swing.JPanel();
 javax.swing.JPanel referencesPanel = new javax.swing.JPanel();
 java.awt.GridBagLayout gridBagLayout1 = new java.awt.GridBagLayout();
 java.awt.BorderLayout borderLayout2 = new java.awt.BorderLayout();
 java.awt.BorderLayout borderLayout3 = new java.awt.BorderLayout();
 java.awt.BorderLayout borderLayout4 = new java.awt.BorderLayout();
 javax.swing.JScrollPane referencesScrollPane = new javax.swing.JScrollPane();
 javax.swing.JTextArea messageArea = new javax.swing.JTextArea();
 javax.swing.border.Border border1;
 javax.swing.border.Border border2;
 javax.swing.JButton cancelButton = new javax.swing.JButton();
 java.awt.GridBagLayout gridBagLayout2 = new java.awt.GridBagLayout();
 javax.swing.JList referencesList = new javax.swing.JList();

 private void jbInit() {
  border1 = javax.swing.BorderFactory.createEmptyBorder(10,10,10,10);
  border2 = javax.swing.BorderFactory.createEmptyBorder(0,10,10,10);
  setLayout(borderLayout1);
  okayButton.setText(I18n.getString("buttonOK")); // "OK"
  removeReferenceButton.setText("Remove Reference");
  removeReferenceButton.addActionListener(new java.awt.event.ActionListener() {
   public void actionPerformed(java.awt.event.ActionEvent e) {
    removeReferenceButton_actionPerformed(e);
    }
   });

  removeAllReferenceButton.setText("Remove All References");
  removeAllReferenceButton.addActionListener(new java.awt.event.ActionListener() {
   public void actionPerformed(java.awt.event.ActionEvent e) {
    removeAllReferenceButton_actionPerformed(e);
    }
   });

  mainPanel.setLayout(gridBagLayout1);
  iconPanel.setLayout(borderLayout2);
  messagePanel.setLayout(borderLayout3);
  referencesPanel.setLayout(borderLayout4);
  messageArea.setText("Message goes here.");
  mainPanel.setBorder(border1);
  buttonPanel.setBorder(border2);
  buttonPanel.setLayout(gridBagLayout2);
  cancelButton.setText(I18n.getString("buttonCancel"));
  referencesList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
  add(buttonPanel, java.awt.BorderLayout.SOUTH);
  add(mainPanel, java.awt.BorderLayout.CENTER);
  buttonPanel.add(okayButton,      new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0
    ,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(8, 8, 8, 4), 0, 0));
  buttonPanel.add(cancelButton,      new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0
    ,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(8, 0, 8, 0), 0, 0));
  buttonPanel.add(removeReferenceButton,       new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0
    ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(8, 0, 8, 8), 0, 0));
  buttonPanel.add(removeAllReferenceButton,       new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0
    ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(8, 0, 8, 8), 0, 0));
  mainPanel.add(iconPanel,   new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
    ,GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0));
  mainPanel.add(messagePanel,   new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0
    ,GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
  messagePanel.add(messageArea, java.awt.BorderLayout.CENTER);
  mainPanel.add(referencesPanel,    new GridBagConstraints(0, 1, 2, 1, 1.0, 1.0
    ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(10, 0, 0, 0), 0, 0));
  referencesPanel.add(referencesScrollPane, java.awt.BorderLayout.CENTER);
  referencesScrollPane.getViewport().add(referencesList, null);
 }

}
